//app.js
const util = require('utils/util.js');

App({

  globalData: {
    userInfo: null,
    accountId: '',
    accessToken: '',
    apiUrl: 'https://wxa.cqultra.cn',
    defaultStyle: { titleBarBackgroundColor: '#E1544C', titleBarFontColor: '#ffffff', backgroundStyle: 'Color:#ffffff;background:#E1544C url(http://brickhu.qiniudn.com/pageBG.png) no-repeat bottom; background-size:100%;' },
    abc: '#000000',
    maxLabelSize: 140,   // chinese char size = 2 else size = 1
    minRecordSeconds: 2,
    disabledPostIds: new Map(),
    accountUpdateTime: 0
  },

  cache: {
    changed: false,
    items: new Map(),
    totalSize: 0,
    maxSize: 6000000,
    cleanup: function () {
      console.log('clean cache');
      let items = this.items;
      let entities = util.mapToList(items);
      entities.sort((a, b) => {
        // 时间最近的优先
        let result = a.value.time - b.value.time;
        if (result == 0) result = a.value.size - b.value.size;
        return result;
      });
      let i = 0;
      while (i < entities.length - 1 && this.totalSize > this.maxSize) {
        let entity = entities[i++];
        items.delete(entity.key);
        wx.removeSavedFile({ filePath: entity.value.path })
        this.changed = true;
        this.totalSize -= entity.value.size;
      }
    },
    restore: function (key) {
      let file = this.items.get(key);
      if (file != null) {
        console.log('hit cache file: ' + key);
        file.time = util.currentTime();
        return file.path;
      } else {
        return null;
      }
    },
    persist: function (key, tempPath, callback) {
      let cache = this;
      wx.getFileInfo({
        filePath: tempPath,
        success: (res) => {
          let size = res.size;
          if (size < cache.maxSize) {
            wx.saveFile({
              tempFilePath: tempPath,
              success: (res) => {
                let savedPath = res.savedFilePath;
                cache.changed = true;
                cache.items.set(key, { path: savedPath, time: util.currentTime(), size: size });
                cache.totalSize += res.size;
                if (cache.totalSize > cache.maxSize) {
                  cache.cleanup();
                }
                callback(savedPath);
              }
            });
          } else {
            callback(tempPath);
          }
        }
      });
    }
  },

  postCache: {
    changed: false,
    maxSize: 10,
    items: new Map(),
    cleanup: function () {
      let reduceSize = this.items.size - this.maxSize;
      if (reduceSize > 0) {
        let entities = util.mapToList(this.items);
        entities.sort((a, b) => {
          // 时间最近的优先
          return a.value.time - b.value.time;
        });
        for (var i = 0; i < reduceSize; i++) {
          let key = entities[i].key;
          this.items.delete(key);
          wx.removeStorage({ key: 'cache:post' + key });
        }
      }
    },
    persist: function (post) {
      let cache = this;
      let key = 'cache:post:' + post.id;
      wx.setStorage({
        key: key,
        data: JSON.stringify(post),
        success: () => {
          cache.items.set(String(post.id), { key: key, time: util.currentTime() });
          cache.cleanup();
          cache.changed = true;
        }
      });
    },
    restore: function (postId) {
      let item = this.items.get(String(postId));
      if (item != null) {
        let skey = 'cache:post:' + postId;
        try {
          let content = wx.getStorageSync(skey);
          let result = JSON.parse(content);
          console.log('hit post cache:' + result.id);
          return result;
        } catch (e) {
          this.items.delete(postId);
          wx.removeStorage({ key: skey });
        }
      }
      return null;
    }
  },

  onLaunch: function () {
    const app = this;
    const globalData = app.globalData
    try {
      let value = wx.getStorageSync('access-token');
      let splitIndex = value.lastIndexOf('@');
      if (splitIndex > 0) {
        globalData.accessToken = value.substring(0, splitIndex);
        globalData.accountId = parseInt(value.substring(splitIndex + 1));
      }
    } catch (e) { }
    wx.getStorage({
      key: 'cache-index',
      success: function (res) {
        let value = res.data;
        try { value = JSON.parse(value); } catch (ignored) { value = null; }
        util.objToMap(value, app.cache.items);
      }
    });
    wx.getStorage({
      key: 'cache-post',
      success: function (res) {
        try { util.objToMap(JSON.parse(res.data), app.postCache.items); } catch (ignored) { }
      },
    });
    wx.getStorage({
      key: 'account-update-time',
      success: (res) => {
        globalData.accountUpdateTime = parseInt(res.data);
        if (isNaN(globalData.accountUpdateTime)) globalData.accountUpdateTime = 0;
      }
    });
  },

  onHide() {
    const cache = this.cache;
    if (cache.changed) {
      wx.setStorage({
        key: 'cache-index',
        data: JSON.stringify(util.mapToObj(cache.items)),
        success: () => { cache.changed = false; }
      });
    }
    const postCache = this.postCache;
    if (postCache.changed) {
      wx.setStorage({
        key: 'cache-post',
        data: JSON.stringify(util.mapToObj(postCache.items)),
        success: () => { postCache.changed = false }
      });
    }
    const globalData = this.globalData;
    wx.setStorage({
      key: 'account-update-time',
      data: globalData.accountUpdateTime,
    });
  },

  loadUserInfo: function (callback) {
    const globalData = this.globalData;
    wx.getUserInfo({
      success: function (data) {
        if (data.userInfo != null) globalData.userInfo = data.userInfo; else console.log(data);
      },
      complete: function () {
        callback(globalData.userInfo);
      }
    });
  },

  refreshAccessToken: function (callback) {
    const app = this;
    const globalData = app.globalData;
    wx.login({
      success: (res) => {
        const code = res.code;
        if (code) {
          wx.request({
            url: app.processUri('accounts/login/weixin'),
            method: 'POST',
            header: { 'code': code, 'Authorization': globalData.accessToken },
            data: globalData.userInfo,
            success: (res) => {
              if (res.statusCode < 200 || res.statusCode >= 300) {
                wx.showToast({ title: '无法登录到系统。' });
                wx.removeStorage({
                  key: 'access-token',
                  success: (data) => {
                    console.log('access-token removed');
                  }
                });
              } else {
                globalData.accessToken = res.data.token;
                globalData.accountId = res.data.accountId;
                wx.setStorage({
                  key: 'access-token',
                  data: globalData.accessToken + '@' + globalData.accountId,
                });
              }
            },
            complete: () => {
              if (callback != null) callback(globalData.accessToken);
            }
          });
        } else {
          wx.showToast({ title: res.errMsg });
          if (callback != null) callback(globalData.accessToken);
        }
      },
      fail: () => {
        wx.showToast({ title: '登录失败' });
        globalData.accessToken = null;
        wx.removeStorage({
          key: 'access-token',
          success: (data) => {
            console.log('access-token removed');
          }
        });
      }
    })
  },

  processUri: function (uri, ...paths) {
    if (uri != null && uri != '' && uri.indexOf('://') < 0) {
      if (!uri.startsWith('/')) uri = '/' + uri;
      uri = this.globalData.apiUrl + uri;
    }
    if (paths != null) {
      for (var p of paths) {
        p = p.toString();
        if (!p.startsWith('/')) p = '/' + p;
        uri += p;
      }
    }
    return uri;
  },

  getStyle: function (styleable) {
    const defaultStyle = this.globalData.defaultStyle;
    let style = defaultStyle;
    if (styleable != null) {
      style = styleable['style'];
      if (typeof (style) == 'string') {
        try {
          style = util.mergeObj(JSON.parse(style), defaultStyle);
        } catch (e) { style = defaultStyle }
      } else style = defaultStyle;
    } else {
      const currentStyle = this.globalData.currentStyle;
      if (currentStyle != null) style = currentStyle;
    }
    return style;
  },

  changeStyle: function (page, styleable, gloablChange = true) {
    const style = this.getStyle(styleable);
    if (styleable != null && gloablChange) this.globalData.currentStyle = style;
    page.setData({
      backgroundStyle: style['backgroundStyle'],
    });
    wx.setNavigationBarColor({
      frontColor: this.globalData.defaultStyle.titleBarFontColor,
      backgroundColor: this.globalData.defaultStyle.titleBarBackgroundColor,
    })
  },

  downloadFile: function (app, uris, index, downloadedPaths, callback) {
    let path = uris[index];
    if (path != null && path != '') {
      path = app.processUri(path);
      let cacheKey = path.toLowerCase();
      let cached = app.cache.restore(cacheKey);
      let checkEnd = () => {
        if (++index >= uris.length) {
          callback(downloadedPaths);
        } else {
          app.downloadFile(app, uris, index, downloadedPaths, callback);
        }
      };
      if (cached != null) {
        downloadedPaths.push(cached);
        checkEnd();
      } else {
        console.log('start download: ' + path);
        wx.downloadFile({
          url: path,
          success: (res) => {
            if (res.statusCode == 200) {
              app.cache.persist(cacheKey, res.tempFilePath, (path) => {
                downloadedPaths.push(path);
                checkEnd();
              });
            }
          },
          fail: () => {
            console.log('download file fail');
            checkEnd();
          }
        });
      }
    }
  },

  downloadFiles: function (uris, callback) {
    this.downloadFile(this, uris, 0, [], (paths) => {
      callback(paths);
    });
  },

})